O que é?

"A computação em nuvem é a entrega sob demanda de poder computacional, armazenamento de banco de dados, aplicativos e outros recursos de TI pela Internet com uma definição de preço conforme o uso."

Como funciona?

"A computação em nuvem oferece uma forma de acessar servidores, armazenamento, bancos de dados e um conjunto amplo de serviços de aplicativos via Internet. Um provedor de serviços em nuvem é proprietária e faz a manutenção do hardware conectado à rede necessário para esses serviços de aplicativos, enquanto você provisiona e utiliza o que precisa por meio de um aplicativo web."

Tipos de serviço em nuvem

  • Infrastructure as a service (IaaS)
  • Platform as a service (PaaS)
  • Software as a service (SaaS)

IaaS

  • Acesso a infraestrutura de servidores, rede ou armazenamento.
  • APIs de alto nível que desreferenciam detalhes de baixo nível, como recursos físicos de computação, armazenamento, particionamento de dados etc.

PaaS

  • Ferramentas para hospedagem de aplicativos web
  • Distribuição de atualizações automáticas

SaaS

  • Oferece um serviço completo, totalmente gerenciado pelo provedor de serviços -Em geral, se refere à serviços destinados ao usuário final

Principais provedores de serviços coud

  • Google Cloud
  • Microsoft Azure
  • IBM Bluemix
  • Amazon Web Services

Amazon Web Services (AWS)

Amazon EC2

O Amazon Elastic Compute Cloud (Amazon EC2) é um serviço flexível, que disponibiliza capacidade computacional, redimensionável e baseada na nuvem no formato de instâncias EC2 que são equivalentes a servidores virtuais.

Nível Gratuito da AWS

  • Nível gratuito de 12 meses: permite que os clientes utilizem gratuitamente o produto até aos limites especificados durante um ano a partir da data de criação da conta.
  • Oferta sempre gratuita: permite que os clientes usem o produto gratuitamente até limites especificados, desde que sejam clientes da AWS.
  • Teste de curto prazo: podem ser usados gratuitamente por um período especificado ou até um limite de tempo não renovável, dependendo do serviço selecionado.

Sob demanda

  • Linux: 0,0084 USD por hora
  • Windows: 0,013 USD por hora

Istâncias spot

  • Linux: 0,0056 USD por hora
  • Windows: 0,0102 USD por hora

Savings Plans

  • Linux: 0,005 USD por hora
  • Windows: 0,0101 USD por hora

Instâncias reservadas

  • Linux: 0,0084 USD por hora
  • Windows: 0,013 USD por hora

Host dedicado

  • Linux e Windows: 2,86 USD por hora

Amazon EC2 Auto Scaling

O Amazon EC2 Auto Scaling ajuda a manter a disponibilidade do aplicativo e permite adicionar ou remover automaticamente instâncias do EC2 de acordo com as condições definidas por você.

Preço mínimo

  • O Amazon EC2 Auto Scaling é habilitado pelo Amazon CloudWatch e não acarreta taxas adicionais.

Spot do Amazon EC2

As instâncias spot do Amazon EC2 permitem aproveitar a capacidade não utilizada do EC2 na Nuvem AWS. Em comparação com a definição de preço sob demanda, as instâncias spot oferecem descontos de até 90%.

Preço mínimo

  • Linux: 0,0056 USD por hora
  • Windows: 0,0102 USD por hora

Recomendações de uso

Big data e análises, Cargas de trabalho conteinerizadas, CI/CD e testes, Web services, Renderização de imagens e mídia, Computação de alta performance

Amazon EC

O Amazon Elastic Container Service (Amazon ECS) é um serviço altamente escalável e de alta performance para a orquestração de contêineres que é compatível com contêineres do Docker e permite executar e escalar facilmente aplicativos conteinerizados na AWS..

Precificação da Amazon EC2

Precificação modelo Fargate

  • 0,0696 USD vCPU/hora
  • 0,0076 USD GB/hora

Recomendações de uso

Big data e análises, Cargas de trabalho conteinerizadas, CI/CD e testes, Web services, Renderização de imagens e mídia, Computação de alta performance

Amazon Lightsail

O Lightsail é uma plataforma de nuvem fácil de usar que oferece tudo o que você precisa para criar aplicativos e sites, incluindo servidores virtuais, armazenamento, bancos de dados gerenciados, gerenciamento de DNS e endereços IP estáticos - tudo por um preço baixo e previsível.

Preço mínimo

  • Planos a partir de 3,50 USD por mês

Recomendações de uso

Alicativos Web Simples, Sites, Softwares Comerciais, Ambientes de teste/desenvolvimento.

Amazon Batch

O AWS Batch possibilita que desenvolvedores, cientistas e engenheiros executem de modo fácil e eficiente centenas de milhares de tarefas de computação em lote na AWS.

Preço mínimo

  • Não há cobrança adicional para o AWS Batch.

Recomendações de uso

Serviços financeiros: análises pós-negociação, ciências biológicas: teste de medicamentos, mídia digital: renderização de efeitos visuais

IBM Cloud

"A plataforma em nuvem da IBM combina a plataforma como um serviço (PaaS) com a infraestrutura como um serviço (IaaS) para fornecer uma experiência integrada. A plataforma escala e suporta pequenas equipes de desenvolvimento e organizações e grandes empresas corporativas."

Plano Lite

  • Gratuito e sem limite de tempo

Pay as you go

  • Pague somente pelo que usar

Assinatura

  • Precificação com desconto customizado

O usuário ganha USD 200 de crédito em seus servidores ao se inscrever no site da IBM Cloud

Servidores Bare Metal

Os servidores bare metal fornecem aos usuários acesso exclusivo ao servidor inteiro. Ao contrário de um servidor virtual com vários locatários, o servidor bare metal puro tem um único locatário e é oferecido sem um hypervisor, eliminando, assim, o efeito “vizinho ruidoso” e qualquer “taxa” de desempenho do hypervisor. Os servidores bare metal podem ser adquiridos em um formato pré-configurado ou configurado de forma customizada para especificações exatas.

Preços mínimos

  • 0,56 USD por hora
  • 325 USD por mês

Microsoft Azure

  • Oferece serviços relativamente parecidos com os da amazon, sendo os mais relevantes para a nossa profissão:
  • Machine learning studio
  • Data Science digital virtual machine (DSDVM)
  • Banco de dados SQL

Machine Learning Studio

  • Funciona de maneira parecida com o jupyter notebook
  • Sistema drag and drop
  • pode executar scripts R e python, sequencialmente
  • Experimentos, pipelines, treinamento de IAs etc.

DSDVM

  • Basicamente uma máquina virtual

  • Acesso remoto facilitado via windows

  • Já vem com a maioria dos aplicativos necessários instalados (Rstudio, Jupyter, Python, Anaconda etc.)

Como acessar?

Google Cloud

  • Sistema de cobrança simples, baseado no número de cores vCPU e GB de RAM

Comparação de custos

A importância do Linux

Estabelecer conexão

# ATENÇÃO: O seguinte código deve ser rodado na ordem estabelecida

# Nome do projeto da sua conta de Google Cloud
projeto <- 'ce2-cloudcomputing' 
# Localização do servidor
local <- 'southamerica-east1-a' 
# Chave criada
conta_chave <- 'chave.json' 

# Colocar varáveis no 'enviroment variables' para outros processos
# executados no R

Sys.setenv(GCE_AUTH_FILE = conta_chave,
           GCE_DEFAULT_PROJECT_ID = projeto,
           GCE_DEFAULT_ZONE = local)


library(googleComputeEngineR)
# Estabelecer projeto global

gce_global_project(projeto)
gce_global_zone(local)

Estabelecer servidor de Rstudio

vm <- gce_vm(template = "rstudio",
             name = "meu-rstudio",
             username = "marcelo", password = "marcelo1234",
             predefined_type = "n1-highmem-2")

## Parar ou iniciar uma instância

gce_vm_stop('meu-rstudio') # Parar

gce_vm_start('meu-rstudio') # Iniciar

Outra alternativa para criação de instâncias

Sequencial vs Paralelo

Sequencial

for (i in 0:185) {
  
  pneustore<- readLines(
    paste0(
      "https://www.pneustore.com.br/c/pneus?q=%3Abest-sellers&page=",
      i))
  
  nome_posicao <- grep(".cantu-products__list__item__name.>",
                       pneustore)
  
  nome_posicao <- nome_posicao + 1
  
  nomes <- sub("</h2>","",pneustore[nome_posicao])
  
  preço_posicao <- nome_posicao + 12
  
  preço[i] <- sub("R\\$","",sub("</del>","",
                                pneustore[preço_antigo_posicao]))

}

Paralelo

url_base <- 
  "https://www.pneustore.com.br/c/pneus?q=%3Abest-sellers&page="
pneustore <- list()


# Função para pegar link de cada página

pegar_link <- function(x){
  links <- str_c(
    'https://www.pneustore.com.br',
    str_replace_all(x[2], '.*href="(.*)" class.*', '\\1'))
}

# Função para pegar o conteúdo de cada página (html)

ler_paginas <- function(qtd){
  for (i in 0:qtd){
    pneustore[[i+1]] <<- readLines(paste0(url_base, i))
  }
}

# Transformar em lista de produtos

lista_produtos <- function(x){
  seps <- str_which(x, '<li class="cantu-products__list__item">')
  
  novo <- c()
  novo[1] <- seps[1]-1
  
  for(i in 1:length(seps)){
    novo[i+1] <- seps[i+1] - seps[i]
  }
  
  novo[length(novo)] <- novo[length(novo)-1]
  novo[length(novo)+1] <- length(x)-sum(novo)
  
  a<-split(x, rep(1:length(novo), novo))
  a[[1]] <- a[[length(a)]] <- NULL
  
  return(a)
}

# Função para pegar preço

preco <- function(x){
  posicao_preco <- str_which(x, "['R$'][' '][0-9.,]{3,10}</del>")
  preco_bruto <- x[posicao_preco]
  preco <- str_replace_all(str_replace_all(
    preco_bruto, '</del>', ''), '.*R\\$ ', '')
  preco <- parse_number(preco, locale = din_br)
  return(preco)
}

  ler_paginas(185)

# Pega link de cada produto
  produtos_bruto <- lapply(pneustore, lista_produtos) 
  
  produtos_bruto <- unlist(produtos_bruto,
                           recursive = F, use.names = F) 
 
# Acessar cada link de cada produto   
  links <- lapply(produtos_bruto, pegar_link) 
  
  produtos <- list()

# Pegar html de cada produto    
  produtos <- lapply(links,
                     function(x) readLines(x, encoding = 'UTF-8')) 
  
  preços <- lapply(produtos_bruto, preco) # Pegar o preço

Loops e tarefas repetitivas usando lapply

Quando você tem uma lista de tarefas repetitivas, pode acelerar isso adicionando mais poder de computação. Se cada tarefa é completamente INDEPENDETE das outras, cada uma em seu próprio núcleo.

Exemplo simples de tarefa no R

Calculando a i-ésima raíz quadrada

raiz <- function(i){
  sqrt(i)
}

x <- 1:200

lapply(x, raiz)

Pacote 'parallel'

require(parallel)
detectCores()
nucleo <- makeCluster(2)

raiz <- function(i){
  sqrt(i)
}

x <- 1:200

parLapply(nucleo,x,raiz)

Pacote 'foreach'

require(foreach)
x <- 1:200

foreach(i = x) %do% { # rodando sequencialmente
  sqrt(i)}

A função foreach retorna uma lista por padrão. Um erro comum é pensar que o foreach é como um loop for. Na verdade, foreach é mais como lapply.

Em paralelo com o Pacote 'doParallel'

require(doParallel)
# Usando a função do pacote 'parallel'
nucleo <- parallel::makeCluster(2) 

# Passo necessário para usar a funcionalidade '%dopar%'
doParallel::registerDoParallel(nucleo) 

x <- 1:200

foreach(i = x) %dopar% { # Atenção: para rodar em paralelo
                         # precisa do '%dopar%'
  sqrt(i)}

Pacote "future"

  • sequential: resolve sequencialmente (Default)

  • multicore: resolve em paralelo em processos bifurcados ('Forking') separados, executando em segundo plano na mesma máquina. Não funciona no Windows.

  • multiprocess: resolve em paralelo, executando em segundo plano na mesma máquina.

  • cluster: resolve em paralelo em sessões separadas de R, executando normalmente em uma ou mais máquinas.

plan(strategy = ... , workers = ...)

Pacote "doFuture"

require("doFuture")
# Parecido com a função 'registerDoParallel' do pacote 'doParallel'
registerDoFuture() 

# Função do pacote future para rodar em paralelo com 2 núcleos
plan(multiprocess, workers = 2) 

x <- 1:200

foreach(i = x) %dopar% {
  sqrt(i)}

Pacote 'furrr'

'purrr' + 'future'

require(furrr)
x <- 1:200

plan(multiprocess, workers = 2)

future_map_dbl(x, raiz)

Importante

Quando terminarmos, precisamos fechar o cluster para que recursos como memória sejam retornados ao sistema operacional.

 # Para as funções do pacote 'parallel'
stopCluster(nucleo)

 # Para as funções do pacote 'doParallel' + 'foreach'
stopImplicitCluster()

 # Para as funções que precisam do pacote 'future'
plan(sequential)

Imagem ilustrativa do tempo gasto de cada função

'Overhead' na computação em paralelo

'Parallel Overhead' é a quantidade de tempo necessária para coordenar tarefas paralelas, em vez de realizar um trabalho útil.

  • Tempo para iniciar uma tarefa

  • Tempo para finalizar uma tarefa

  • Tempo de sincronização

Simulação

lista_geracoes<- function(pop_inicial,geracoes,lambda=2.5){
#n.1
n.1<- matrix(data=NA,pop_inicial,2)
n.1[,1]<- sample(1:2,pop_inicial,replace = T)
casal.1<- paste0("1.",1:min(as.numeric(table(n.1[,1]))))

### Sorteando os casais 
if ((as.numeric(table(n.1[,1]))[1])>=(as.numeric(table(n.1[,1]))[2])){
  n.1[n.1[,1]==2,2] <- sample(casal.1)   
  x<-logical(length = length(n.1[,1]))
  x[sample(which(n.1[,1]==1),length(casal.1))]<- TRUE
  n.1[x,2] <- sample(casal.1) 
} else {
  n.1[n.1[,1]==1,2] <- sample(casal.1)   
  x<-logical(length = length(n.1[,1]))
  x[sample(which(n.1[,1]==2),length(casal.1))]<- TRUE
  n.1[x,2] <- sample(casal.1) 
}
lista<- list()
lista_casais <- list()
lista_casais[[1]]<- casal.1

Criando as gerações

for (w in 1:geracoes){
  vetor_pais<- character(length = geracoes)
  for (i in 1:(length(lista_casais[[w]]))){
    vetor_pais[w]<- rep(lista_casais[[w]][i],rpois(1,lambda))
  }
  lista[[w]]<-matrix(data=NA,length(vetor_pais[w]),3)
  lista[[w]][,1]<- vetor_pais[w]
  lista[[w]][,2]<-sample(1:2,length(vetor_pais[w]),replace = T)
  ## Criando os casais da geração
  
  #eval(parse(text=paste0('casal.',w+1,'<-paste0(w+1,".",1)
  
  #assign(paste0("casal.",w+1), paste0(w+1,".",1)
  
  lista_casais[[w+1]]<-paste0(w+1,".",1:min(as.numeric(table(lista[[w]][,2]))))

Tempo no computador

Ou 6,51 horas!

Agora na nuvem

Tempo em nuvem

  • Ou 1,41 horas! Rodando a simulação por 4 vezes

  • 1,41 vs 26,04 horas

Por fim